From a6ef3afe23e597f66be58a3cba0aeae8bfbfd0ec Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Tue, 3 Aug 2004 08:12:57 +0000 Subject: [PATCH] bitkeeper revision 1.1108.53.1 (410f49091nUueqW95skYILdr1AOlpQ) Fix NMI error code to correctly print a crash dump before hanging. --- xen/arch/x86/nmi.c | 7 ++++--- xen/arch/x86/traps.c | 42 +++++++++++++++++++++++++++++-------- xen/arch/x86/x86_32/entry.S | 16 ++++++++++---- xen/drivers/char/console.c | 11 ++++++++++ xen/drivers/char/serial.c | 7 +++++++ xen/include/xen/console.h | 3 +++ xen/include/xen/serial.h | 2 ++ 7 files changed, 72 insertions(+), 16 deletions(-) diff --git a/xen/arch/x86/nmi.c b/xen/arch/x86/nmi.c index af287444eb..ec12834ee7 100644 --- a/xen/arch/x86/nmi.c +++ b/xen/arch/x86/nmi.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -271,7 +272,6 @@ void touch_nmi_watchdog (void) void nmi_watchdog_tick (struct pt_regs * regs) { - extern spinlock_t console_lock; extern void die(const char * str, struct pt_regs * regs, long err); int sum, cpu = smp_processor_id(); @@ -285,8 +285,9 @@ void nmi_watchdog_tick (struct pt_regs * regs) * before doing the oops ... */ alert_counter[cpu]++; - if (alert_counter[cpu] == 5*nmi_hz) { - console_lock = SPIN_LOCK_UNLOCKED; + if ( alert_counter[cpu] == 5*nmi_hz ) + { + console_force_unlock(); die("NMI Watchdog detected LOCKUP on CPU", regs, cpu); } } diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 8de5573d27..dbc91d5114 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -140,7 +141,7 @@ void show_registers(struct pt_regs *regs) unsigned long esp; unsigned short ss; - esp = (unsigned long) (®s->esp); + esp = (unsigned long)(®s->esp); ss = __HYPERVISOR_DS; if ( regs->xcs & 3 ) { @@ -271,7 +272,6 @@ DO_ERROR_NOCODE( 0, "divide error", divide_error) asmlinkage void do_double_fault(void) { - extern spinlock_t console_lock; struct tss_struct *tss = &doublefault_tss; unsigned int cpu = ((tss->back_link>>3)-__FIRST_TSS_ENTRY)>>1; @@ -295,7 +295,7 @@ asmlinkage void do_double_fault(void) printk("************************************\n"); /* Lock up the console to prevent spurious output from other CPUs. */ - spin_lock(&console_lock); + console_force_lock(); /* Wait for manual reset. */ for ( ; ; ) ; @@ -472,9 +472,11 @@ asmlinkage void do_general_protection(struct pt_regs *regs, long error_code) die("general protection fault", regs, error_code); } -asmlinkage void mem_parity_error(unsigned char reason, struct pt_regs * regs) +asmlinkage void mem_parity_error(unsigned char reason, struct pt_regs *regs) { - printk("NMI received. Dazed and confused, but trying to continue\n"); + console_force_unlock(); + + printk("\n\nNMI received. Dazed and confused, but trying to continue\n"); printk("You probably have a hardware problem with your RAM chips\n"); /* Clear and disable the memory parity error line. */ @@ -482,18 +484,40 @@ asmlinkage void mem_parity_error(unsigned char reason, struct pt_regs * regs) outb(reason, 0x61); show_registers(regs); - panic("PARITY ERROR"); + + printk("************************************\n"); + printk("CPU%d MEMORY ERROR -- system shutdown\n", smp_processor_id()); + printk("System needs manual reset.\n"); + printk("************************************\n"); + + /* Lock up the console to prevent spurious output from other CPUs. */ + console_force_lock(); + + /* Wait for manual reset. */ + for ( ; ; ) ; } -asmlinkage void io_check_error(unsigned char reason, struct pt_regs * regs) +asmlinkage void io_check_error(unsigned char reason, struct pt_regs *regs) { - printk("NMI: IOCK error (debug interrupt?)\n"); + console_force_unlock(); + + printk("\n\nNMI: IOCK error (debug interrupt?)\n"); reason = (reason & 0xf) | 8; outb(reason, 0x61); show_registers(regs); - panic("IOCK ERROR"); + + printk("************************************\n"); + printk("CPU%d I/O ERROR -- system shutdown\n", smp_processor_id()); + printk("System needs manual reset.\n"); + printk("************************************\n"); + + /* Lock up the console to prevent spurious output from other CPUs. */ + console_force_lock(); + + /* Wait for manual reset. */ + for ( ; ; ) ; } static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index f3b6885d5a..c75c035e4b 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -602,7 +602,7 @@ ENTRY(nmi) # reload DS and ES when handling them. inb $0x61,%al testb $0x80,%al - jne nmi_parity_err + je nmi_parity_err testb $0x40,%al jne nmi_io_err movl %eax,%ebx @@ -660,14 +660,22 @@ nmi_parity_err: movl $(__HYPERVISOR_DS),%edx movl %edx,%ds movl %edx,%es - jmp SYMBOL_NAME(mem_parity_error) + movl %esp,%edx + push %edx + push %eax + call SYMBOL_NAME(mem_parity_error) + ud2 nmi_io_err: movl $(__HYPERVISOR_DS),%edx movl %edx,%ds movl %edx,%es - jmp SYMBOL_NAME(io_check_error) - + movl %esp,%edx + push %edx + push %eax + call SYMBOL_NAME(io_check_error) + ud2 + .data ENTRY(hypercall_table) .long SYMBOL_NAME(do_set_trap_table) /* 0 */ diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 15219b67c7..23456261e3 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -433,6 +433,17 @@ void console_endboot(int disable_vga) switch_serial_input(); } +void console_force_unlock(void) +{ + console_lock = SPIN_LOCK_UNLOCKED; + serial_force_unlock(sercon_handle); +} + +void console_force_lock(void) +{ + spin_lock(&console_lock); +} + /* * ************************************************************** diff --git a/xen/drivers/char/serial.c b/xen/drivers/char/serial.c index e6ae6c60b9..60e6b02c32 100644 --- a/xen/drivers/char/serial.c +++ b/xen/drivers/char/serial.c @@ -459,3 +459,10 @@ unsigned char serial_getc(int handle) spin_unlock_irqrestore(&uart->lock, flags); return c; } + +void serial_force_unlock(int handle) +{ + uart_t *uart = &com[handle & SERHND_IDX]; + if ( handle != -1 ) + uart->lock = SPIN_LOCK_UNLOCKED; +} diff --git a/xen/include/xen/console.h b/xen/include/xen/console.h index 2a30ef1231..628eb044d4 100644 --- a/xen/include/xen/console.h +++ b/xen/include/xen/console.h @@ -19,4 +19,7 @@ long read_console_ring(unsigned long, unsigned int, unsigned int); void init_console(void); void console_endboot(int disable_vga); +void console_force_unlock(void); +void console_force_lock(void); + #endif diff --git a/xen/include/xen/serial.h b/xen/include/xen/serial.h index 3640fd036f..6fcc67f228 100644 --- a/xen/include/xen/serial.h +++ b/xen/include/xen/serial.h @@ -43,4 +43,6 @@ void serial_puts(int handle, const unsigned char *s); */ unsigned char serial_getc(int handle); +void serial_force_unlock(int handle); + #endif /* __XEN_SERIAL_H__ */ -- 2.30.2